/**

 * @author admin

 * 2014年8月12日

 */

package com.tmall.testgen.client.genfile.genproject;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.JavaProject;

import com.tmall.testgen.client.ClientDataCenter;
import com.tmall.testgen.client.config.ConfigUtil;
import com.tmall.testgen.client.genfile.TotalGenHandler;
import com.tmall.testgen.client.genfile.genjava.GenCodeCenter;
import com.tmall.testgen.client.genfile.genjava.bo.classpathentry.Attribute;
import com.tmall.testgen.client.genfile.genjava.bo.classpathentry.ClassPathEntry;
import com.tmall.testgen.client.genfile.genxml.GenXMLCenter;
import com.tmall.testgen.client.genfile.xls.XlsUtil;
import com.tmall.testgen.common.bo.interact.back.InterceptInfo;
import com.tmall.testgen.common.util.FileUtil;
import com.tmall.testgen.common.util.StringUtil;

public class ProjectGenerator{
	public static String commonpackage="com.tmall.testgen.common";
private static Set<String>jars=new HashSet<String>();
	
	static{
		jars.add("commons-beanutils-1.7.0.jar");
		jars.add("commons-dbcp-1.2.2.jar");
		jars.add("commons-lang-2.6.jar");
		jars.add("commons-logging-1.1.3.jar");
		jars.add("dbunit-2.4.4.jar");
		jars.add("itest-1.3.jar");
		jars.add("logback-classic-1.1.1.jar");
		jars.add("logback-core-1.1.1.jar");
		jars.add("mockAgent.jar");
		
		jars.add("poi-3.2-FINAL.jar");
		jars.add("slf4j-api-1.6.6.jar");
		jars.add("unitils-core-3.1.jar");
		jars.add("xpp3-1.1.4c.jar");
		jars.add("xstream-1.4.7.jar");
		jars.add("hsf.app.spring-1.4.9.jar");
		jars.add("hsf.lib-1.4.9.jar");
		jars.add("hsf.services-1.4.9.jar");
		jars.add("hsfunit-1.0.5-SNAPSHOT.jar");
		jars.add("javax.servlet-api-3.0.1.jar");
		jars.add("velocity-1.6.jar");
		jars.add("junit-4.8.1.jar");
		
		jars.add("spring-aop-3.2.9.RELEASE.jar");
		jars.add("spring-beans-3.2.9.RELEASE.jar");
		jars.add("spring-context-3.2.9.RELEASE.jar");
		jars.add("spring-context-support-3.2.9.RELEASE.jar");
		jars.add("spring-core-3.2.9.RELEASE.jar");
		jars.add("spring-expression-3.2.9.RELEASE.jar");
		jars.add("spring-jdbc-3.2.9.RELEASE.jar");
		jars.add("spring-tx-3.2.9.RELEASE.jar");
		jars.add("spring-web-3.2.9.RELEASE.jar");
		jars.add("spring-webmvc-3.2.9.RELEASE.jar");
		
		jars.add("javassist-3.0.jar");
	}
	
	/**
	 * 
	 * @param testProjecPath
	 * @param toGenProjectInfo 格式：projectName$sourceFolder
	 * @param velocityEngine
	 * @param packagePath
	 * @param content
	 * @throws Exception
	 */
    public static  String  genProject(String testProjecPath,String testProjectName,String toBeGenTestClassName,String toBeGenProjectInfo,VelocityEngine velocityEngine,List<InterceptInfo> toBeGenInfos) throws Exception {
       
        String toBeGenProjectName=toBeGenProjectInfo;
        String toBeGenProjectSourceFolder="src";
        if(toBeGenProjectInfo.lastIndexOf("$")>1){
            toBeGenProjectName=toBeGenProjectInfo.substring(0, toBeGenProjectInfo.lastIndexOf("$"));
            toBeGenProjectSourceFolder=toBeGenProjectInfo.substring(toBeGenProjectInfo.lastIndexOf("$")+1);
        }
        testProjecPath=StringUtil.normalizePath(testProjecPath);
        if(testProjecPath.endsWith("/"))
            testProjecPath=testProjecPath.substring(0, testProjecPath.length()-1);
        
        if(toBeGenProjectSourceFolder.endsWith("/"))
            toBeGenProjectSourceFolder=toBeGenProjectSourceFolder.substring(0, toBeGenProjectSourceFolder.length()-1);
        
        String projectRootPath=testProjecPath.substring(0,testProjecPath.lastIndexOf("/"));
        
        IJavaProject testProject=  getJavaProject(testProjectName);
        IJavaProject toBeGenProject=  getJavaProject(toBeGenProjectName);
        
        
        String toBeGenProjectRootPath=projectRootPath+"/"+toBeGenProjectName;
        if(toBeGenProject!=null&&toBeGenProject.exists()){
            toBeGenProjectRootPath=toBeGenProject.getProject().getLocation().toString();
        }
        
    	 //生成jar
    	 for(String jar:jars){
    	     FileUtil.copyLib("/lib/"+jar, toBeGenProjectRootPath+"/lib");
    	 }
    	 
    	 
    	
    	 
    	 
    	 Map<String,IClasspathEntry> entries=new LinkedHashMap<String,IClasspathEntry>();
    	 
    	//初始化lib
    	 Set<String> srcs=initJarPath(toBeGenProjectRootPath,toBeGenProject,testProject,entries,jars);
    	 
    	 String sourceFolderPath=toBeGenProjectRootPath+"/"+toBeGenProjectSourceFolder;
         
    	 
    	 List<ClassPathEntry> classPathEntries=new ArrayList<ClassPathEntry>();
    	 
    	 for(String key:entries.keySet()){
    	     IClasspathEntry entry=entries.get(key);
    	     ClassPathEntry tem=new ClassPathEntry(); 
    	     tem.setKind(entry.getEntryKind());
    	     tem.setPath(entry.getPath().toString());
    	     if(entry.getSourceAttachmentPath()!=null)
    	         tem.setSourcepath(entry.getSourceAttachmentPath().toString());
    	     
    	     List<Attribute> attsR=new ArrayList<Attribute>();
    	     tem.setAttributes(attsR);
    	     
    	     IClasspathAttribute[] atts= entry.getExtraAttributes();
    	     if(atts!=null)
    	         for(IClasspathAttribute ca:atts){
    	             Attribute att=new Attribute();
    	             att.setName(ca.getName());
    	             att.setValue(ca.getValue());
    	             attsR.add(att);
    	         }
    	     classPathEntries.add(tem);
    	 }
    	 List<String> srcRes=new ArrayList<String>();
    	 srcs.add("/"+toBeGenProjectName+"/"+toBeGenProjectSourceFolder);
    	 for(String src:srcs){
    	     srcRes.add(src.replaceAll("/"+toBeGenProjectName+"/",""));
    	 }
    	 
    	 Map<String,Object> map=new HashMap<String,Object>();
        
         List<String> refs=new ArrayList<String>();
         refs.add(testProjectName);
         refs.addAll(ConfigUtil.getRefProjectNames(testProjectName));
         map.put("refProjectNames", refs);
         
         
         String outputLocation="/"+toBeGenProjectName+"/bin";
         if(toBeGenProject!=null&&toBeGenProject.exists())
             outputLocation=toBeGenProject.getOutputLocation().toString();
         
         map.put("outputLocation", outputLocation);
         map.put("currentProjectName", toBeGenProjectName);
         
    	 createEclipesFile(toBeGenProjectRootPath,velocityEngine,map,"project",false);  
    	
         map.put("classPathEntries", classPathEntries);
         map.put("srcs", srcRes);
         
         createEclipesFile(toBeGenProjectRootPath,velocityEngine,map,"classpath",false);  
         
         
    	 
    	 
    	//生成java文件内容
         String fileContent=GenCodeCenter.genTestClassContent(velocityEngine, toBeGenTestClassName, toBeGenInfos);
         FileUtil.createFile(sourceFolderPath+"/"+StringUtil.replaceD2G(toBeGenTestClassName)+".java", fileContent, true);
         
         
    	//生成文件
    	genFiles(sourceFolderPath,velocityEngine);
    	
    	//备份xls
    	String location =projectRootPath+"/"+toBeGenProjectName+"/"+toBeGenProjectSourceFolder+"/"+StringUtil.replaceD2G(toBeGenTestClassName);
		XlsUtil.getInstace().backupData2Xls(location, ClientDataCenter.getInstance().getDbInfo(), ClientDataCenter.getInstance().getSqlSnap());

    
		//将参数及结果写入xml
        GenXMLCenter.writeParamAndResultToXML(sourceFolderPath+"/"+StringUtil.replaceD2G(toBeGenTestClassName), toBeGenInfos);
        
        return toBeGenProjectRootPath;
    }
    
    private static void genFiles(String sourceFolderPath,VelocityEngine velocityEngine) throws Exception{
    	 
     	Map<String,Object> map=new HashMap<String,Object>();
     	map.put("commonpackage", commonpackage);
     	
     	
     	createFile(sourceFolderPath,velocityEngine,map,"logback.xml",false);	
     	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.dbunit.operation.BackupExistDataOperation.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.dbunit.operation.DeleteRefDataOperation.java",false);	
     	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.dbunit.AbstractOperation.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.dbunit.TestGenDatabaseOperation.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.dbunit.TestGenDataTypeFactory.java",false);	
     	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.itest.TestGenITestDataSetListener.java",false);	
     	
     	map.put("dbInfo", ClientDataCenter.getInstance().getDbInfo());
     	createFile(sourceFolderPath,velocityEngine,map,"extend.itest.TestGenSpringContextListener.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.web.TestGenMockServletContext.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.web.TestGenMockServletConfig.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"extend.web.WebXmlInfo.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"util.AutoConfigReplacer.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"util.Comparator.java",false);	
        createFile(sourceFolderPath,velocityEngine,map,"util.CommonUtil.java",false);
        
     	createFile(sourceFolderPath,velocityEngine,map,"bo.MethodSnap.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"bo.DBInfo.java",false);	
     	
     	createFile(sourceFolderPath,velocityEngine,map,"BaseTest.java",false);	
     	createFile(sourceFolderPath,velocityEngine,map,"ClassInfo.java",false);	
     	
		int showdB=(ClientDataCenter.getInstance().getDbInfo()!=null&&ClientDataCenter.getInstance().getDbInfo().getUrl().length()>0)?1:0;
		map.put("showdB", showdB);
		createFile(sourceFolderPath,velocityEngine,map,"TestGenSpringContextBaseCase.java",false);
    }
	private  static String  genJavaContent(VelocityEngine velocityEngine,String templatePath,Map<String,Object>params) throws Exception{
		 
	     Template template = velocityEngine.getTemplate(TotalGenHandler.templateRootPath+templatePath);
	     VelocityContext velocityContext = new VelocityContext();
	     if(params!=null){
	    	 for(String key:params.keySet()){
	    		 velocityContext.put(key, params.get(key));
	    	 }
	     }
	     
	     StringWriter stringWriter = new StringWriter();
	     template.merge(velocityContext, stringWriter);
	     return stringWriter.toString();
	}

    
    private  static void createFile(String packageRootPath, VelocityEngine velocityEngine,Map<String,Object> map,String packagePath,boolean needDeleteOldFile) throws Exception{
    	String templatePath=StringUtil.replaceD2G(packagePath.substring(0, packagePath.lastIndexOf(".")));
    	String content=genJavaContent(velocityEngine,templatePath+".vm",map);
    	
    	int pos=packagePath.lastIndexOf(".");
    	if(pos==-1)
    	    pos=packagePath.length();
    	
    	String completePath=packageRootPath+"/"+(commonpackage+"."+packagePath.substring(0, pos)).replaceAll("\\.", "/")+packagePath.substring(pos);
    	
    	
        FileUtil.createFile(completePath, content,needDeleteOldFile);
        
    }
    private  static void createEclipesFile(String projectRootPath, VelocityEngine velocityEngine,Map<String,Object> map,String fileName,boolean needDeleteOldFile) throws Exception{
        
        
        String content=genJavaContent(velocityEngine,fileName+".vm",map);
        
        FileUtil.createFile(projectRootPath+"/."+fileName, content,needDeleteOldFile);
        
    }
    
    

	/**
	 * 获取指定工程的依赖
	 * @param projectName
	 * @return
	 * @throws Exception
	 */
	private static  List<IClasspathEntry> getClasspathEntries(String projectName)throws Exception{
		List<String> projects=new ArrayList<String>();
		projects.add(projectName);
		projects.addAll(ConfigUtil.getRefProjectNames(projectName));
		
		
		Set<String> pathes=new HashSet<String>();
		List<IClasspathEntry> entries=new ArrayList<IClasspathEntry>();
		
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		for(String project:projects){
			
	        IProject tProject = root.getProject(project);
	        IJavaProject tjProject = JavaCore.create(tProject);
	        IClasspathEntry[]  temEntry=tjProject.getRawClasspath();
	        for(IClasspathEntry te:temEntry){
	        	if(pathes.contains(te.getPath().toString()))
	        		continue;
	        	if(te.getEntryKind()==IClasspathEntry.CPE_LIBRARY||te.getEntryKind()==IClasspathEntry.CPE_VARIABLE||te.getEntryKind()==IClasspathEntry.CPE_PROJECT){
		        	pathes.add(te.getPath().toString());
		        	entries.add(te);
	        	}else if(te.getEntryKind()==IClasspathEntry.CPE_CONTAINER){
	        	    if(te.getPath().toString().contains("JRE_CONTAINER")){
	        	        pathes.add(te.getPath().toString());
	                    entries.add(te);
	        	    }else{
	        	        entries.addAll(Arrays.asList(JavaCore.getClasspathContainer(te.getPath(), getJavaProject(projectName)).getClasspathEntries()));
	        	    }
	        	   // IClasspathEntry[] entries=JavaCore.getClasspathContainer(i.getPath(), javaProject).getClasspathEntries();
	        	   
	        	}
	        }
		}
		return entries;
	}
	
	/**
	 * 
	 * @param toBeGenProjectRootPath
	 * @param toBeGenProject 可能不存在
	 * @param testProject
	 * @param jarPathMap
	 * @param jarPathes
	 * @throws Exception
	 */
	private static Set<String>  initJarPath( String toBeGenProjectRootPath,IJavaProject toBeGenProject,IJavaProject testProject, Map<String,IClasspathEntry> jarPathMap,Set<String> jarPathes) throws Exception{
	   
	    
		if(jarPathes!=null){
			//新加入的path
			for(String path:jarPathes){
				String fpath=toBeGenProjectRootPath+"/lib/"+path;
				jarPathMap.put(fpath, JavaCore.newLibraryEntry(new Path(fpath), null, null));
			}
		}

//        // 获取默认的JRE库
//       IClasspathEntry[] jreLibrary = PreferenceConstants.getDefaultJRELibrary();
//       for(IClasspathEntry lib:jreLibrary){
//           jarPathMap.put(lib.getPath().toString(), lib);
//       }
       
		Set<String> srcs=new HashSet<String>();
		if(toBeGenProject!=null&&toBeGenProject.exists()){
			 // 获取原来的build path
	        IClasspathEntry[] oldClasspathEntries = toBeGenProject.getRawClasspath();
	        if(oldClasspathEntries!=null){
		        for(IClasspathEntry old:oldClasspathEntries){
		            if(old.getEntryKind()==IClasspathEntry.CPE_SOURCE)
		                srcs.add(old.getPath().toString());
		            else
		                jarPathMap.put(old.getPath().toString(), old);
		        }
	        }
		}
        

	    String testProjecName=testProject.getProject().getName();
        List<IClasspathEntry> list = new ArrayList<IClasspathEntry>();
        list.addAll(getClasspathEntries(testProjecName));
        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IProject targetProject = root.getProject(testProjecName);
        list.add(JavaCore.newProjectEntry( JavaCore.create(targetProject).getPath()));
        
        
        for(IClasspathEntry entry:list){
        	String path=entry.getPath().toString();
        	String name=path.substring( path.lastIndexOf("/")+1);
        	if(jarPathes.contains(name)){
        		continue;
        	}
        	
        	jarPathMap.put(entry.getPath().toString(), entry);
        }
        
        return srcs;
	}
	

	private static IJavaProject getJavaProject(String targetProjecName) throws Exception{
        
        // 获取工作区
       IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
       IProject targetProject = root.getProject(targetProjecName);
       
       // 转化成java工程
       return  JavaCore.create(targetProject);
   }
}
